from enum import Enum
import os, json

class Message:
    def __init__(self, msg: str) -> None:
        self.msg = msg
    
    def build(self):
        return {
            "message": self.msg
        }

def message(msg: str):
    return Message(msg).build()

class JsonResponse:
    def __init__(self, code: int, data: dict) -> None:
        self.code = code
        self.data = data
    
    def build(self):
        return {
            "code": self.code,
            "data": self.data
        }

def jsonify(code: int, data: dict):
    return JsonResponse(code, data).build()

class Status(Enum):
    OK_200 = 200
    FileNotFound_404 = 404
    Forbidden_403 = 403

class File:
    def __init__(self, path) -> None:
        self.path = path
        # if not os.path.exists(path):raise FileExistsError(path)
    
    def read(self) -> bytes:
        with open(self.path, 'rb') as f:
            return f.read()
    
    def write(self, data: bytes):
        with open(self.path, 'wb') as f:
            f.write(data)
        return self
    
    def readStr(self) -> str:
        with open(self.path, 'r', encoding='utf-8') as f:
            return f.read()
    
    def readJson(self) -> str:
        return json.loads(self.readStr())
    
    def writeJson(self, data):
        return self.writeStr(json.dumps(data))
    
    def writeStr(self, data: str):
        with open(self.path, 'w', encoding='utf-8') as f:
            f.write(data)
        return self
    
    def append(self, data: str):
        with open(self.path, 'a', encoding='utf-8') as f:
            f.write(data)
        return self
    
    def create(self):
        try:
            os.makedirs(os.path.split(self.path)[0])
        except FileExistsError:
            pass
        if os.path.exists(self.path):
            return
        f=open(self.path, 'x', encoding="utf-8")
        f.close()
        return self
    
    @property
    def name(self):
        return os.path.split(self.path)[1]

class Dir:
    def __init__(self, path:str) -> None:
        self.path = path
        # if not os.path.exists(path):raise FileExistsError(path)
        self.children_file: list[File] = []
        self.children_dir : list[Dir ] = []
    
    def walk(self):
        for i in os.listdir(self.path):
            if os.path.isfile(i):
                self.children_file.append(File(os.path.join(self.path, i)))
            elif os.path.isdir(i):
                self.children_dir.append(Dir(os.path.join(self.path, i)))
    
    def get_file(self, name):
        for i in self.children_file:
            if i.name == name:
                return i
        return None
    
    def get_dir(self, name):
        for i in self.children_dir:
            if i.name == name:
                return i
    
    @property
    def name(self):
        return os.path.split(self.path)[1]

class Mod(File):
    def __init__(self, name, mod_version, game_version, translate_name=None) -> None:
        self.modname = name
        self.mod_version = mod_version
        self.game_version = game_version
        self.translate_name = translate_name
        self.loader = "unknown"
        self.authors = ""
        self.description = ""
        if translate_name is None:
            super().__init__(os.path.join(f"{name}-{mod_version}-{game_version}-[].jar"))
        else:
            super().__init__(os.path.join(f"{name}-{mod_version}-{game_version}-[{translate_name}].jar"))
    
    def get_file(self, rootdir):
        return os.path.join(rootdir, "mods", self.modname, self.path)
    
    @staticmethod
    def build_by_fullname(name: str):
        name = os.path.splitext(name)[0]
        name = name.split('-')
        modname = name[0]
        modver = name[1]
        gamever = name[2]
        if len(name) > 3:
            traname = name[3]
            return Mod(modname, modver, gamever, traname)
        return Mod(modname, modver, gamever)
    
    def toJson(self):
        return {
            "name": self.modname,
            "mod_version": self.mod_version,
            "game_version": self.game_version,
            "display_name": self.translate_name,
            "authors": self.authors,
            "loader": self.loader,
            "description": self.description
        }
    
    def rebuild(self):
        if self.translate_name is None:
            super().__init__(os.path.join(f"{self.modname}-{self.mod_version}-{self.game_version}-[].jar"))
        else:
            super().__init__(os.path.join(f"{self.modname}-{self.mod_version}-{self.game_version}-[{self.translate_name}].jar"))

class Target:
        def __init__(self, target_path: str) -> None:
            self.target_path = target_path
        
        def trans(this, trans_map: dict, name: str):
            r = this.target_path
            for k,v in trans_map.items():
                r = r.replace("$"+k, v)
            return r+name
        
class TargetDir(Target, Dir):
    def __init__(self, path: str, target_path: str) -> None:
        Target.__init__(self, target_path=target_path)
        Dir.__init__(self, path=path)
    
    def walk(self):pass
    
    def __str__(self) -> str:
        return '{"name": "' + self.name + '","target": ' + self.target_path + '}'
    
class TargetFile(Target, File):
    def __init__(self, path: str, target_path: str) -> None:
        Target.__init__(self, target_path=target_path)
        File.__init__(self, path=path)
    
    def __str__(self) -> str:
        return '{"name": "' + self.name + '","target": ' + self.target_path + '}'

class Package(Dir):
    class Config:
        def __init__(self, name: str, mods: list, files: list, dirs: list, pack_version: str, game_version: str) -> None:
            self.name = name
            self.mods = mods
            self.files = files
            self.dirs = dirs
            self.pack_version = pack_version
            self.game_version = game_version

    def __init__(self, json_path: str) -> None:
        self.config = File(json_path).readJson()
        self.config = self.Config(self.config["name"], self.config["mods"], self.config["files"], self.config["dirs"], self.config["pack_version"], self.config["game_version"])
        super().__init__(self.config.name)
        self.children_dir.append(TargetDir("mods", "$version/"))
        for mod in self.config.mods:
            self.children_dir[0].children_file.append(Mod(mod["name"], mod["mod_version"], mod["game_version"]))
        for _dir in self.config.dirs:
            self.children_dir.append(TargetDir(_dir["name"], _dir["target"]))
        for file in self.config.files:
            self.children_file.append(TargetFile(file["name"], file["target"]))
    
    def toJson(self):
        return {
            "name": self.config.name,
            "pack_version": self.config.pack_version,
            "game_version": self.config.game_version
        }